Skip to content

Fix {{FIELD:tags}} suggestions from vault tag index#1016

Merged
chhoumann merged 1 commit intomasterfrom
fix/issue-671-field-tags-suggestions
Dec 13, 2025
Merged

Fix {{FIELD:tags}} suggestions from vault tag index#1016
chhoumann merged 1 commit intomasterfrom
fix/issue-671-field-tags-suggestions

Conversation

@chhoumann
Copy link
Copy Markdown
Owner

@chhoumann chhoumann commented Dec 13, 2025

Fixes #671.

What changed

  • {{FIELD:tags}} / {{FIELD:tag}} now suggests existing tags from Obsidian's vault-wide tag index (metadataCache.getTags()), so tags show up even when they're not present as a frontmatter field.
  • When FIELD filters are present (e.g. |folder:, |tag:, exclusions), we fall back to scanning the filtered file set to preserve filtering semantics.

Tests

  • Added a regression test: src/utils/FieldValueCollector.issue671.test.ts.
  • bun run test passes.

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced tag collection to properly retrieve tags from the vault's metadata cache, including both frontmatter and inline tags in field value suggestions.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 13, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
quickadd Ready Ready Preview Dec 13, 2025 1:40pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 13, 2025

Walkthrough

Modifications to the tag collection workflow introduce specialized handling for the FIELD:tags template placeholder. A new test file validates the fix for issue #671. The core changes add dedicated methods to extract tags from the vault's metadata cache and markdown files with batch processing, while maintaining backward compatibility with existing fallback mechanisms.

Changes

Cohort / File(s) Summary
Test for issue #671
src/utils/FieldValueCollector.issue671.test.ts
New test file mocking Obsidian APIs and verifying that collectFieldValuesProcessed returns tag names from the metadata cache index (ai/technology, cook/hoven).
Tag collection logic
src/utils/FieldValueCollector.ts
Introduces specialized tag-based collection path in collectFieldValuesRaw with three new internal functions: collectTagValues (routing logic), collectAllVaultTags (cache-based extraction), and collectTagValuesFromFiles (file-based extraction with batch processing). Handles both frontmatter array and scalar tag formats, normalizes tag strings, and maintains existing Dataview fallback.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Batch file processing implementation: Verify correctness of the batching mechanism and edge cases with large file counts
  • Tag normalization logic: Confirm proper handling of trimming, leading # removal, and deduplication across multiple sources
  • Frontmatter parsing: Ensure both array and scalar forms of tags and tag fields are correctly extracted
  • Fallback flow: Validate that tag-specific collection gracefully falls back to Dataview and manual collection paths when appropriate

Poem

🐰 A vault of tags was lost in the mist,
Some scattered tags the seeker had missed.
Now batch by batch, we gather them whole,
From cache and files, a complete collection's goal!
No more shall cook/hoven hide from sight,
The template feast is finally complete and bright! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: fixing {{FIELD:tags}} suggestions to use the vault tag index.
Linked Issues check ✅ Passed The pull request addresses all objectives from issue #671: ensures all vault tags appear as suggestions, fixes the missing tags discrepancy, and preserves filtering behavior.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing {{FIELD:tags}} suggestions and implementing vault tag index integration as specified in issue #671.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/issue-671-field-tags-suggestions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Use Obsidian's tag index for tags/tag field suggestions when no file filters are applied, with a filtered-files fallback.

Adds a regression test for issue #671.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/utils/FieldValueCollector.ts (2)

111-132: LGTM - Consider adding debug logging for troubleshooting.

The tag normalization correctly strips # prefixes and handles the untyped Obsidian API. The empty catch block at line 127-129 silently swallows errors, which is acceptable since the caller falls back to file-based collection. However, routing errors through the logger utility could aid debugging in production.

-	} catch {
-		// ignore and fall back to file-based collection
-	}
+	} catch (e) {
+		// Fall back to file-based collection; log for debugging
+		console.debug?.("collectAllVaultTags: vault tag index unavailable", e);
+	}

134-200: The batch processing and tag extraction from frontmatter (tags/tag) and inline hashtags (metadataCache.tags) are correctly implemented.

Minor design note: collectTagValues returns early when tags are found (line 72), which bypasses the manual collection path that would call InlineFieldParser.getFieldValues if filters.inline is true. This means Dataview-style inline fields like tags:: work would not be collected if vault or frontmatter tags exist. However, no search results show users combining |inline:true with tag fields, and this appears to be the intentional design where tags receive special-case handling rather than generic field handling.

src/utils/FieldValueCollector.issue671.test.ts (1)

10-31: Good regression test coverage for Issue #671.

The test correctly validates that vault tags are included in suggestions when no filters are present. The mock setup is appropriate, and clearing the cache before each test prevents cross-test contamination.

Consider adding edge case coverage:

it("uses file-based collection when filters are present", async () => {
	const app = new App();
	// @ts-expect-error - getTags exists in Obsidian but is not typed
	app.metadataCache.getTags = () => ({ "#vaultTag": 1 });
	app.vault.getMarkdownFiles = () => [];

	// With folder filter, should use file-based scan (empty result since no files)
	const values = await collectFieldValuesProcessed(app, "tags", { folder: "notes" });
	expect(values).not.toContain("vaultTag");
});

it("handles 'tag' field name (singular)", async () => {
	const app = new App();
	// @ts-expect-error
	app.metadataCache.getTags = () => ({ "#test": 1 });
	app.vault.getMarkdownFiles = () => [];

	const values = await collectFieldValuesProcessed(app, "tag", {});
	expect(values).toContain("test");
});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c13731 and 5665876.

📒 Files selected for processing (2)
  • src/utils/FieldValueCollector.issue671.test.ts (1 hunks)
  • src/utils/FieldValueCollector.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Source code lives in src/: core logic under engine/, services/, and utils/; Svelte UI in src/gui; shared types in src/types; settings entry in src/quickAddSettingsTab.ts

Files:

  • src/utils/FieldValueCollector.issue671.test.ts
  • src/utils/FieldValueCollector.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Biome enforces tab indentation (width 2), LF endings, and an 80-character line guide; align editor settings
Use camelCase for variables and functions
Prefer type-only imports in TypeScript files
Route logging through the logger utilities for consistent output
Structure production code so Obsidian dependencies are injected behind interfaces; unit tests target pure logic and swap in adapters or tests/obsidian-stub.ts

Files:

  • src/utils/FieldValueCollector.issue671.test.ts
  • src/utils/FieldValueCollector.ts
src/**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components

Files:

  • src/utils/FieldValueCollector.issue671.test.ts
  • src/utils/FieldValueCollector.ts
🧠 Learnings (2)
📚 Learning: 2025-12-09T21:20:52.398Z
Learnt from: CR
Repo: chhoumann/quickadd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T21:20:52.398Z
Learning: Applies to tests/**/*.{ts,tsx} : Add regression coverage for bug fixes

Applied to files:

  • src/utils/FieldValueCollector.issue671.test.ts
📚 Learning: 2025-12-09T21:20:52.398Z
Learnt from: CR
Repo: chhoumann/quickadd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T21:20:52.398Z
Learning: Applies to src/**/*.{ts,tsx} : Structure production code so Obsidian dependencies are injected behind interfaces; unit tests target pure logic and swap in adapters or `tests/obsidian-stub.ts`

Applied to files:

  • src/utils/FieldValueCollector.issue671.test.ts
🧬 Code graph analysis (2)
src/utils/FieldValueCollector.issue671.test.ts (3)
src/utils/FieldSuggestionCache.ts (1)
  • FieldSuggestionCache (8-171)
tests/obsidian-stub.ts (1)
  • App (23-51)
src/utils/FieldValueCollector.ts (1)
  • collectFieldValuesProcessed (27-42)
src/utils/FieldValueCollector.ts (2)
src/utils/FieldSuggestionParser.ts (1)
  • FieldFilter (1-12)
src/utils/EnhancedFieldSuggestionFileFilter.ts (1)
  • EnhancedFieldSuggestionFileFilter (4-170)
🔇 Additional comments (2)
src/utils/FieldValueCollector.ts (2)

69-73: LGTM!

The special-case handling for tag fields integrates cleanly with the existing fallback flow. Normalizing to lowercase ensures case-insensitive matching, and returning early when tags are found avoids unnecessary Dataview calls.


95-109: LGTM!

The filter detection logic correctly distinguishes when vault-wide index retrieval is appropriate versus when file-level scanning is needed to respect user-specified filters.

@chhoumann chhoumann merged commit 8a19e12 into master Dec 13, 2025
4 checks passed
@chhoumann chhoumann deleted the fix/issue-671-field-tags-suggestions branch December 13, 2025 13:57
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 2.9.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@github-actions
Copy link
Copy Markdown

🚀 Release has been published: v2.9.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] {{FIELD:tags}} doesn't suggest some tags

1 participant